#include <libex.h>
#if  !defined(__WIN32__) && !defined(__WIN__)
/**
 * \param value valor a ser convertido para char
 * \param result resultado da conversão
 * \param base para conversão
 * \return O número inteiro passado no value convertido para char
 */
char* itoa(int value, char* result, int base) 
	{
	// check that the base if valid
	if (base < 2 || base > 36) 
		{ 
		*result = '\0'; 
		return result; 
		}
	
	char* ptr = result, *ptr1 = result, tmp_char;
	int tmp_value;
	
	do 
		{
		tmp_value = value;
		value /= base;
		*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
		} while ( value );
	
	// Apply negative sign
	if (tmp_value < 0) 
		{
		*ptr++ = '-';
		}
	*ptr-- = '\0';
	while(ptr1 < ptr) 
		{
		tmp_char = *ptr;
		*ptr--= *ptr1;
		*ptr1++ = tmp_char;
		}
	return result;
	}
#endif

/**
 * \param dias_menos quantidade de dias a ser subtraído do dia atual.
 * \return A data subtraida o numero de dias passado em dias_menos
 */
char *data_otima(int dias_menos)
	{
	time_t rawtime;
  	struct tm * timeinfo;
  	char *buffer;
	int ano, mes, dia, diff;

  	time ( &rawtime );
  	timeinfo = localtime ( &rawtime );

	buffer = new char[12];
  	strftime (buffer,5,"%Y",timeinfo);
	ano = atoi(buffer);
	strftime (buffer,3,"%m",timeinfo);
	mes = atoi(buffer);
	strftime (buffer,3,"%d",timeinfo);
	dia = atoi(buffer);

	diff = dia - dias_menos;
	if ( diff <= 0 )
		{
		switch(mes)
			{
			case 1:
				{
				dia = 31 + diff;
				ano = ano - 1;
				break;
				}
			case 2:
			case 4:
			case 6:
			case 8:
			case 9:
			case 11:
				{
				dia = 31 + diff;
				break;
				}
			case 3:
				{
				if ( (ano % 4) == 0 )
					{
					dia = 29 + diff;
					}
				else
					{
					dia = 28 + diff;
					}
				break;
				}
			case 5:
			case 7:
			case 10:
			case 12:
				{
				dia = 30 - diff;
				break;
				}
			}
		mes = mes - 1;
		}
	else
		{
		sprintf(buffer,"%d-%02d-%02d",ano,mes,diff);
		}
	return (buffer);
	}

/**
 * \return A data atual do sistema.
 */
char *hoje()
	{
	time_t rawtime;
  	struct tm * timeinfo;
  	char *buffer;

	time ( &rawtime );
  	timeinfo = localtime ( &rawtime );

	buffer = new char[12];

	strftime (buffer,11,"%Y-%m-%d",timeinfo);

	return (buffer);
	}

/**
 * \return A hora atual do sistema.
 */
char *agora()
	{
	time_t rawtime;
  	struct tm * timeinfo;
  	char *buffer;

	time ( &rawtime );
  	timeinfo = localtime ( &rawtime );

	buffer = new char[10];

	strftime (buffer,9,"%H:%M:%S",timeinfo);

	return (buffer);
	}

/**
 * \param hoje Data de referência em string
 * \param modo formato da data passada:\n
 * 1 - AAAA-MM-DD\n
 * 2 - DD/MM/AAAA\n
 * \return O proximo dia útil.
 */
string prox_dia(string hoje, int modo)
	{
	time_t rawtime;
	struct tm *timeinfo;
	int diff,dia, mes, ano;
	char *buffer;
	string retorno;

	switch (modo)
		{
		case 1:
			{
			dia = atoi(hoje.substr(8,2).c_str());
			mes = atoi(hoje.substr(5,2).c_str());
			ano = atoi(hoje.substr(0,4).c_str());
			break;
			}
		case 2:
			{
			ano = atoi(hoje.substr(6,4).c_str());
			mes = atoi(hoje.substr(3,2).c_str());
			dia = atoi(hoje.substr(0,2).c_str());
			break;
			}
		default:
			{
			return false;
			break;
			}
		}
	cout << ano << "::" << mes << "::" << dia << endl;
	dia++;
	switch(mes)
		{
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
			{
			diff = dia - 31;
			if (dia > 31)
				{
				mes++;
				dia = diff;
				}
			break;
			}
		case 4:
		case 6:
		case 9:
		case 11:
			{
			diff = dia - 30;
			if (dia > 30)
				{
				mes++;
				dia = diff;
				}
			break;
			}
		case 2:
			{
			if ((ano % 4) == 0)
				{
				diff = dia - 29;
				if (dia > 29)
					{
					mes++;
					dia = diff;
					}
				}
			else
				{
				diff = dia - 28;
				if (dia > 28)
					{
					mes++;
					dia = diff;
					}
				}
			break;
			}
		case 12:
			{
			diff = dia - 31;
			if (dia > 31)
				{
				ano++;
				mes = 1;
				dia = diff;
				}
			break;
			}
		}
	time (&rawtime);
	timeinfo = localtime ( &rawtime );
  	timeinfo->tm_year = ano - 1900;
  	timeinfo->tm_mon = mes - 1;
  	timeinfo->tm_mday = dia;
	//timeinfo->tm_mday++;

  	/* call mktime: timeinfo->tm_wday will be set */
  	mktime ( timeinfo );
	if (timeinfo->tm_wday == 0)
		{
		dia += 1;
		}
	if (timeinfo->tm_wday == 6)
		{
		dia += 2;
		}

	switch(mes)
		{
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
			{
			diff = dia - 31;
			if (dia > 31)
				{
				mes++;
				dia = diff;
				}
			break;
			}
		case 4:
		case 6:
		case 9:
		case 11:
			{
			diff = dia - 30;
			if (dia > 30)
				{
				mes++;
				dia = diff;
				}
			break;
			}
		case 2:
			{
			if ((ano % 4) == 0)
				{
				diff = dia - 29;
				if (dia > 29)
					{
					mes++;
					dia = diff;
					}
				}
			else
				{
				diff = dia - 28;
				if (dia > 28)
					{
					mes++;
					dia = diff;
					}
				}
			break;
			}
		case 12:
			{
			diff = dia - 31;
			if (dia > 31)
				{
				ano++;
				mes = 1;
				dia = diff;
				}
			break;
			}
		}
  	timeinfo->tm_year = ano - 1900;
  	timeinfo->tm_mon = mes - 1;
  	timeinfo->tm_mday = dia;

	buffer = new char[15];

	strftime (buffer,12,"%Y-%m-%d",timeinfo);

	retorno.clear();
	retorno.append(buffer);

	return (retorno);
	}

/**
 * \param data recebe a data que será escrita por extenso.
 * \param formato indica o formato de entrada da data:\n
 * 1 - AAAA-MM-DD\n
 * 2 - DD/MM/AAAA\n
 * \return A data passada escrita por extenso.
 */
char *data_extenso(char *data, int formato)
	{
	string data_f;
	string mes_f[12];
	int mes;
	char *retorno;

		{
		//Inicializando meses
		mes_f[0].clear();
		mes_f[0].append("janeiro");
		mes_f[1].clear();
		mes_f[1].append("fevereiro");
		mes_f[2].clear();
		mes_f[2].append("março");
		mes_f[3].clear();
		mes_f[3].append("abril");
		mes_f[4].clear();
		mes_f[4].append("maio");
		mes_f[5].clear();
		mes_f[5].append("junho");
		mes_f[6].clear();
		mes_f[6].append("julho");
		mes_f[7].clear();
		mes_f[7].append("agosto");
		mes_f[8].clear();
		mes_f[8].append("setembro");
		mes_f[9].clear();
		mes_f[9].append("outubro");
		mes_f[10].clear();
		mes_f[10].append("novembro");
		mes_f[11].clear();
		mes_f[11].append("dezembro");
		}
	retorno = new char[200];
	data_f.clear();
	data_f.append(data);
	switch (formato)
		{
		case 1:
			{
			strcpy(retorno,data_f.substr(8,2).c_str());
			strcat(retorno," de ");
			mes = atoi(data_f.substr(5,2).c_str());
			strcat(retorno,mes_f[mes-1].c_str());
			strcat(retorno," de ");
			strcat(retorno,data_f.substr(0,4).c_str());
			break;
			}
		}
  	return (retorno);
	}

/**
 * \param data recebe a data a ser formatada.
 * \param saida especifica o formato de saída da data:
 * 1 - AAAA-MM-DD
 * 2 - DD/MM/AAAA
 * \return A data formatada conforme especificada na saida.
 */
char *data_formatada(char *data, int saida)
	{
	char *retorno;
	int aux;
	string data_tmp;

	retorno = new char[12];
	data_tmp.clear();
	data_tmp.append(data);
	switch(saida)
		{
		case 1:
			{
			aux = data_tmp.find("-");
			if (aux != string::npos)
				{
				strcpy(retorno,data);
				}
			else
				{
				strcpy(retorno,data_tmp.substr(6,4).c_str());
				strcat(retorno,"-");
				strcat(retorno,data_tmp.substr(3,2).c_str());
				strcat(retorno,"-");
				strcat(retorno,data_tmp.substr(0,2).c_str());
				}
			break;
			}
		case 2:
			{
			aux = data_tmp.find("/");
			if (aux != string::npos)
				{
				strcpy(retorno,data);
				}
			else
				{
				strcpy(retorno,data_tmp.substr(8,2).c_str());
				strcat(retorno,"/");
				strcat(retorno,data_tmp.substr(5,2).c_str());
				strcat(retorno,"/");
				strcat(retorno,data_tmp.substr(0,4).c_str());
				}
			break;
			}
		}
	return retorno;
	}

/**
 * \param documento recebe o número do documento que será aplicada a máscara.
 * \param tipo Especificar o tipo de dados:\n
 * 1 - CPF\n
 * 2 - CNPJ\n
 * \param saida Especificar o tipo de retorno:\n
 * 1 - Remover mascara\n
 * 2 - Aplicar mascara\n
 * \return O documento passado formatado conforme o parametro especificado na saida.
 */
char *masc_doc(char *documento, int tipo, int saida)
	{
	char *retorno;
	int i,len,j;
	string doc_f, doc;

	retorno = new char[20];
	doc_f.clear();
	doc.clear();
	switch(tipo)
		{
		case 1:
			{
			switch(saida)
				{
				case 1:
					{
					len = strlen(documento);
					j = 0;
					for (i=0; i < len; i++)
						{
						if (!isdigit(documento[i]))
							{
							i++;
							}
						retorno[j] = documento[i];
						j++;
						}
					retorno[j] = '\0';
					break;
					}
				case 2:
					{
					//documento = masc_doc(documento,1,1);
					len = strlen(documento);
					j = 0;
					for (i=0; i < len; i++)
						{
						if ((i == 3)||(i == 6))
							{
							retorno[j] = '.';
							j++;
							}
						if (i == 9)
							{
							retorno[j] = '-';
							j++;
							}
						retorno[j] = documento[i];
						j++;
						}
					retorno[j] = '\0';
					break;
					}
				}
			break;
			}
		case 2:
			{
			switch(saida)
				{
				case 1:
					{
					len = strlen(documento);
					j = 0;
					for (i=0; i < len; i++)
						{
						if (!isdigit(documento[i]))
							{
							i++;
							}
						retorno[j] = documento[i];
						j++;
						}
					retorno[j] = '\0';
					break;
					}
				case 2:
					{
					//documento = masc_doc(documento,1,1);
					len = strlen(documento);
					j = 0;
					for (i=0; i < len; i++)
						{
						if ((i == 2)||(i == 5))
							{
							retorno[j] = '.';
							j++;
							}
						if (i == 8)
							{
							retorno[j] = '/';
							j++;
							}
						if (i == 12)
							{
							retorno[j] = '-';
							j++;
							}
						retorno[j] = documento[i];
						j++;
						}
					retorno[j] = '\0';
					break;
					}
				}
			break;
			}
		}
	return retorno;
	}

/**
 * \param texto string a ser convertida.
 * \return String convertida para maiúculo
 */
string ParaMaiusculos(string texto)
	{
	unsigned int i;

	for(i=0;i<texto.length();i++)
   	{
    texto[i] = toupper(texto[i]);
   	}
  return texto;
	}

/**
 * \param texto string a ser convertida.
 * \return String convertida para minúsculo.
 */
string ParaMinusculos(string texto)
	{
	unsigned int i;

	for(i=0;i<texto.length();i++)
   	{
    texto[i] = tolower(texto[i]);
   	}
  return texto;
	}

/**
 * \param inbuf texto a ser convertido.
 * \param modo especifica o tipo de conversão.\n
 * 1 - UTF-4\n
 * 2 - UTF-8\n
 * \return O texto convertido no formato especificado no modo.
 */
char *converter(char *inbuf, int modo)
	{
	int len, i, j, l, letr[2];
	char *outbuf;

	len = strlen(inbuf);
	//cout << inbuf << endl;
	outbuf = new char[len+1];
	j=0;
	for (i=0; i < len; i++)
		{
		letr[0] = (int) inbuf[i];
		if (letr[0] < 0)
			{
			//cout << inbuf[i] << endl;
			letr[1] = (int) inbuf[i+1];
			if (letr[1] < 0)
				{
				i++;
				for (l=0; l < MAX_MAP; l++)
					{
				
					//cout << letr[0] << " " << letr[1] << " = " << Mapeamento[l].part1 << " " << Mapeamento[l].part2 << endl;
					if ((letr[0] == Mapeamento[l].part1)&&(letr[1] == Mapeamento[l].part2))
						{
						if (modo == 1)
							{
							outbuf[j] = Mapeamento[l].let_oc[0];
							j++;
							}
						else if (modo == 2)
							{
							strcat(outbuf,Mapeamento[l].octal);
							j = strlen(outbuf);
							}
						break;
						}
					}
				}
			else
				{
				outbuf[j] = inbuf[i];
				j++;
				}
			}
		else
			{
			outbuf[j] = inbuf[i];
			j++;
			}
		}
	outbuf[j] = '\0';
	//cout << outbuf << endl;
	return (outbuf);
	}

/**
 * \param documento recebe a string com o documento a ser validado.
 * \param tipo especifica o tipo de documento passado.\n
 * 1 - CPF\n
 * 2 - CNPJ\n
 * \return Verdadeiro ou Falso validando o documento passado.
 */
bool checar_doc(char *documento, int tipo)
	{
	string digitado;
	int digitos[14],dv[2],i,mult;

	digitado.clear();
	digitado = documento;
	switch(tipo)
		{
		case 1:
			{
			if (digitado.length() == 11)
				{
				dv[0] = dv[1] = 0;
				for (i=0; i < 11; i++)
					{
					digitos[i] = digitado[i] - 48;
					if (i < 9)
						{
						dv[0] = dv[0] + digitos[i]*(i+1);
						}
					if (i < 10)
						{
						dv[1] = dv[1] + digitos[i]*i;
						}	
					}
				//cout << dv[0] << " - " << dv[1] << endl;
				dv[0] =  dv[0] % 11;
				dv[1] =  dv[1] % 11;
				//cout << dv[0] << "=" << digitos[9] << endl;
				//cout << dv[1] << "=" << digitos[10] << endl;
				if (dv[0] == 10)
					{
					dv[0] = 0;
					}
				if (dv[1] == 10)
					{
					dv[1] = 0;
					}
				if ((dv[0] != digitos[9])||(dv[1] != digitos[10]))
					{
					return false;
					}
				}
			break;
			}
		case 2:
			{
			if (digitado.length() == 14)
				{
				dv[0] = dv[1] = 0;
				for (i=0; i < 14; i++)
					{
					digitos[i] = digitado[i] - 48;
					if (i < 12)
						{
						mult = 6+i;
						if (mult >= 10)
							{
							mult = mult - 8;
							}
						dv[0] = dv[0] + digitos[i]*mult;
						//cout << digitos[i] << "*" << mult  << "=" << digitos[i]*mult << endl;
						//cout << dv[0] << endl;
						}
					if (i < 13)
						{
						mult = 5+i;
						if (mult >= 10)
							{
							mult = mult - 8;
							}										
						dv[1] = dv[1] + digitos[i]*mult;
						}	
					}
				//cout << dv[0] << " - " << dv[1] << endl;
				dv[0] =  dv[0] % 11;
				dv[1] =  dv[1] % 11;
				//cout << dv[0] << "=" << digitado[12] << endl;
				//cout << dv[1] << "=" << digitado[13] << endl;
				if (dv[0] == 10)
					{
					dv[0] = 0;
					}
				if (dv[1] == 10)
					{
					dv[1] = 0;
					}
				if ((dv[0] != digitos[12])||(dv[1] != digitos[13]))
					{
					return false;
					}
				}
			break;
			}
		}
	return true;
	}

/**
 * \param valor recebe o valor que será colocada a separação de milhares.
 * \param tipo especifica como o valor está sendo passado.
 * 0 - com casas decimais\n
 * 1 - sem casas decimais\n
 * \return O valor com as devidas separações na casa dos milhares.
 */
string casa_milhar(char *valor, int tipo)
	{
	string retorno, AUX;
	int i,j,x;

	retorno.clear();
	AUX.clear();
	AUX.append(valor);
	j=0;
	x=0;
	for (i=AUX.length()-1; i >= 0; i--)
		{
		//cout << AUX[i] << " = " << i << " = " << j << endl;
		if (tipo == 0)
			{
			if ((j > 5)&&((j % 3)== 0))
				{
				//cout << "." << endl;
				retorno = "."+retorno;
				}
			}
		else if (tipo == 1)
			{
			if ((j > 2)&&((j % 3)== 0))
				{
				//cout << "." << endl;
				retorno = "."+retorno;
				}
			}
		retorno = AUX[i]+retorno;
		j++;
		}
	return (retorno);
	}

/**
 * \param valor recebe o valor que será formatado.
 * \param modo especifica como o valor será formatado.\n
 * 1 - substitui , por .\n
 * 2 - substitui . por ,\n
 * \return O valor formatado conforme especificado no modo.
 */
string valor_formatado(char *valor, int modo)
	{
	int i;
	string AUX;

	AUX.clear();
	AUX.append(valor);
	if (AUX.length() > 0)
		{
		switch(modo)
			{
			case 1:
				{
				i = AUX.find (',');
				if (i != string::npos)
					{
					AUX[i] = '.';
					}
				break;
				}
			case 2:
				{
				i = AUX.find ('.');
				if (i != string::npos)
					{
					AUX[i] = ',';
					}					
				break;
				}
			}
		}
	//cout << AUX << endl;
	return (AUX);
	}
/**
 * \param texto Texto a ser tratado os caracteres especiais
 */
char* converter_markup(char *texto)
	{
	int len, i, j, l;
	char *retorno;

	len = strlen(texto);
	retorno = new char[(len*2)];
	j = 0;
	for (i=0; i < len; i++)
		{
		for (l=0; l < MAX_MARK; l++)
			{
			if (texto[i] == Markup_Map[l].car[0])
				{
				strcat(retorno,Markup_Map[l].car_m);
				j = strlen(retorno);
				}
			else
				{
				retorno[j] = texto[i];
				j++;
				}
			break;
			}
		}
	retorno[j] = '\0';
	return retorno;
	}

/**
 * \param data data base para o calculo
 * \param meses quantidade de meses do nascimento
 */
char* data_nasc(char *data, int meses)
	{
	int dia, mes, ano, i, tam, j, c, diff;
	char *buffer;

	tam = strlen(data);
	buffer = (char *)malloc (sizeof(char)*(tam+1));
	if (buffer)
		{
		j = 0;
		c = 0;
		for (i=0; i < tam; i++)
			{
			if (data[i] != '-')
				{
				buffer[c] = data[i];
				c++;
				}
			else
				{
				buffer[c] = '\0';
				//printf("%s\n",buffer);
				if ( j == 0)
					{	
					ano = atoi (buffer);
					}
				else if (j == 1)
					{
					mes = atoi(buffer);
					}
				c = 0;
				j++;
				}
			}
		buffer[c] = '\0';
		dia = atoi(buffer);
		//printf ("Dia %d - Mês %d - Ano %d\n", dia, mes, ano);
		diff = mes - meses;
		while ( diff <= 0 )
			{
			diff = diff + 12;
			ano = ano - 1;
			}
		sprintf (buffer,"%04d-%02d-%02d", ano, diff, dia);
		return (buffer);
		}
	else
		{
		exit (1);
		}
	}

/**
 * \param hora_i hora inicial
 * \param hora_f hora final
 * \return diferença em minutos
 */
int dif_hora (char *hora_i, char *hora_f)
	{
	int hora_in[3], hora_fi[3], retorno, i, j, x;
	char aux_i[3],aux_f[3];

	retorno = 0;
	j = 0;
	x = 0;
	for (i=0; i < strlen(hora_i); i++)
		{
		if (hora_i[i] != ':')
			{
			aux_i[j] = hora_i[i];
			aux_f[j] = hora_f[i];
			j++;
			}
		else
			{
			aux_i[j] = '\0';
			hora_in[x] = atoi(aux_i);
			aux_f[j] = '\0';
			hora_fi[x] = atoi(aux_f);
			x++;
			j = 0;
			}
		}
	aux_i[j] = '\0';
	hora_in[x] = atoi(aux_i);
	aux_f[j] = '\0';
	hora_fi[x] = atoi(aux_f);
	retorno = ((hora_fi[0]-hora_in[0])*60)+(hora_fi[1]-hora_in[1]);
	return(retorno);
	}

/**
 * /param texto valor a ser convertido e ajustado
 * /return double convertido e ajustado
 */
double char2double(const char *texto)
	{
	int n, n_a, p_n;
	float valor;
	float inteira, decimal;
	char n_aux[32];
	n_a = 0;
	p_n = 0;
	for (n=0; n < strlen(texto); n++)
		{
		if (texto[n] != '.')
			{
			n_aux[n_a] = texto[n];
			n_a++;
			}
		else
			{
			p_n = 1;
			n_aux[n_a+1] = '\0';
			n_a=0;
			inteira = strtof(n_aux,NULL);
			n_aux[n_a] = '\0';
			}
		}
	if (p_n == 0)
		{
		inteira = strtof(n_aux,NULL);
		decimal = 0;
		}
	else
		{
		if (n_a == 1)
			{
			n_aux[n_a] = '0';
			n_a++;
			}
		if (n_a > 2)
			{
			n_a = 2;
			}
		n_aux[n_a] = '\0';
		decimal = strtof(n_aux,NULL);
		}
	//cout << inteira << endl;
	//cout << decimal << endl;
	valor = inteira + (decimal/100);
	//cout << valor << endl;
	//cout << (((valor-inteira)*100)-decimal) << endl;
	/*if ((((valor-inteira)*100)-decimal) > 0.5 )
		{
		valor -= 0.005000;
		}*/
	return ((double)valor);
	}

/**
 * Função para gerar MD5 de um arquivo em específico
 * /param arquivo caminho do arquivo a ser checado 
 * /return char * string de checagem 
 */
/*char *file2md5(const char *arquivo)
	{
	unsigned char c[MD5_DIGEST_LENGTH];
	int i;
    FILE *inArquivo = fopen (arquivo, "rb");
    MD5_CTX contexto;
    int bytes;
    unsigned char dados[1024];
	char *retorno, *aux;

	if (inArquivo == NULL) 
		{
		retorno = new char[1024];
        sprintf(retorno,"Arquivo %s não acessível.\n", arquivo);
        return retorno;
    	}
		
	MD5_Init (&contexto);
    while ((bytes = fread (dados, 1, 1024, inArquivo)) != 0)
		{
        MD5_Update (&contexto, dados, bytes);
		}
    MD5_Final (c,&contexto);
		
	fclose (inArquivo);
	
	retorno = new char[MD5_DIGEST_LENGTH*2];
	strcpy(retorno,"");
	for(i = 0; i < MD5_DIGEST_LENGTH; i++)
		{
		aux = new char[4];
		sprintf(aux,"%02x", c[i]);
		strcat(retorno,aux);
		delete aux;
		}
		
	return retorno;
	}*/

/**
 * /param buffer string que será limpada
 */
char *limpar (const char *buffer)
	{
	char *output;
	int i,j,tam;

	tam = strlen(buffer);
	output = new char[tam+1];
	for (i=0,j=0; i < tam; i++)
		{
		if (buffer[i] != ' ')
			{
			output[j] = buffer[i];
			j++;
			}
		}
	output[j] = '\0';
	return output;
	}